/**
 * 网络请求模块 - 提供基于fetch的网络请求功能
 */

/**
 * 默认配置
 */
const DEFAULT_CONFIG = {
  timeout: 10000,
  baseURL: '',
  headers: {
    'Content-Type': 'application/json'
  },
  credentials: 'same-origin'
};

/**
 * 错误类型
 */
class RequestError extends Error {
  constructor(message, code, response) {
    super(message);
    this.name = 'RequestError';
    this.code = code;
    this.response = response;
  }
}

/**
 * 创建超时控制器
 * @param {number} timeout 超时时间（毫秒）
 * @returns {Object} 包含signal和cleanup的对象
 */
function createTimeoutController(timeout) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => {
    controller.abort();
  }, timeout);

  return {
    signal: controller.signal,
    cleanup: () => clearTimeout(timeoutId)
  };
}

/**
 * 构建完整URL
 * @param {string} baseURL 基础URL
 * @param {string} url 请求URL
 * @returns {string} 完整URL
 */
function buildURL(baseURL, url) {
  if (!baseURL || url.startsWith('http')) {
    return url;
  }

  const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
  const path = url.startsWith('/') ? url : '/' + url;

  return base + path;
}

/**
 * 处理请求参数
 * @param {string} url URL
 * @param {Object} params 参数对象
 * @returns {string} 处理后的URL
 */
function handleParams(url, params) {
  if (!params || typeof params !== 'object') {
    return url;
  }

  const searchParams = new URLSearchParams();
  Object.keys(params).forEach(key => {
    if (params[key] !== undefined && params[key] !== null) {
      searchParams.append(key, String(params[key]));
    }
  });

  const queryString = searchParams.toString();
  if (!queryString) return url;

  const separator = url.includes('?') ? '&' : '?';
  return url + separator + queryString;
}

/**
 * 处理响应数据
 * @param {Response} response fetch响应对象
 * @returns {Promise} 处理后的数据
 */
async function handleResponse(response) {
  const contentType = response.headers.get('content-type') || '';

  let data;
  if (contentType.includes('application/json')) {
    data = await response.json();
  } else if (contentType.includes('text/')) {
    data = await response.text();
  } else if (contentType.includes('application/octet-stream')) {
    data = await response.arrayBuffer();
  } else {
    data = await response.blob();
  }

  if (!response.ok) {
    throw new RequestError(
      `HTTP Error ${response.status}: ${response.statusText}`,
      response.status,
      {
        status: response.status,
        statusText: response.statusText,
        data
      }
    );
  }

  return data;
}

/**
 * 核心请求函数
 * @param {string} url 请求URL
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
async function request(url, options = {}) {
  // 合并配置
  const config = {
    ...DEFAULT_CONFIG,
    ...options,
    headers: {
      ...DEFAULT_CONFIG.headers,
      ...options.headers
    }
  };

  // 构建URL
  const fullURL = buildURL(config.baseURL, url);
  const finalURL = handleParams(fullURL, config.params);

  // 处理请求体
  let body = config.data;
  if (body && typeof body === 'object' && !(body instanceof FormData)) {
    if (config.headers['Content-Type']?.includes('application/json')) {
      body = JSON.stringify(body);
    }
  }

  // 构建fetch选项
  const fetchOptions = {
    method: config.method || 'GET',
    headers: config.headers,
    credentials: config.credentials,
    body: body
  };

  // 设置超时控制
  let timeoutController = null;
  if (config.timeout > 0) {
    timeoutController = createTimeoutController(config.timeout);
    fetchOptions.signal = timeoutController.signal;
  }

  try {
    // 发起请求
    const response = await fetch(finalURL, fetchOptions);
    const data = await handleResponse(response);

    // 请求成功，清理超时计时器
    if (timeoutController) {
      timeoutController.cleanup();
    }

    return data;
  } catch (error) {
    // 清理超时计时器
    if (timeoutController) {
      timeoutController.cleanup();
    }

    // 处理错误
    if (error.name === 'AbortError') {
      throw new RequestError('Request timeout', 'TIMEOUT');
    } else if (error instanceof RequestError) {
      throw error;
    } else {
      throw new RequestError(error.message, 'NETWORK_ERROR', error);
    }
  }
}

/**
 * GET请求
 * @param {string} url 请求URL
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function get(url, options = {}) {
  return request(url, { ...options, method: 'GET' });
}

/**
 * POST请求
 * @param {string} url 请求URL
 * @param {any} data 请求数据
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function post(url, data, options = {}) {
  return request(url, { ...options, method: 'POST', data });
}

/**
 * PUT请求
 * @param {string} url 请求URL
 * @param {any} data 请求数据
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function put(url, data, options = {}) {
  return request(url, { ...options, method: 'PUT', data });
}

/**
 * DELETE请求
 * @param {string} url 请求URL
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function del(url, options = {}) {
  return request(url, { ...options, method: 'DELETE' });
}

/**
 * PATCH请求
 * @param {string} url 请求URL
 * @param {any} data 请求数据
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function patch(url, data, options = {}) {
  return request(url, { ...options, method: 'PATCH', data });
}

/**
 * HEAD请求
 * @param {string} url 请求URL
 * @param {Object} options 选项
 * @returns {Promise} 请求结果
 */
export function head(url, options = {}) {
  return request(url, { ...options, method: 'HEAD' });
}

/**
 * 并发请求
 * @param {Array} requests 请求数组
 * @returns {Promise} 所有请求的结果
 */
export function all(requests) {
  return Promise.all(requests);
}

/**
 * 竞速请求（返回最快的结果）
 * @param {Array} requests 请求数组
 * @returns {Promise} 最快的请求结果
 */
export function race(requests) {
  return Promise.race(requests);
}

/**
 * 请求拦截器管理
 */
const interceptors = {
  request: [],
  response: []
};

/**
 * 添加请求拦截器
 * @param {Function} onFulfilled 成功处理函数
 * @param {Function} onRejected 失败处理函数
 * @returns {number} 拦截器ID
 */
export function addRequestInterceptor(onFulfilled, onRejected) {
  const id = interceptors.request.length;
  interceptors.request.push({ onFulfilled, onRejected });
  return id;
}

/**
 * 添加响应拦截器
 * @param {Function} onFulfilled 成功处理函数
 * @param {Function} onRejected 失败处理函数
 * @returns {number} 拦截器ID
 */
export function addResponseInterceptor(onFulfilled, onRejected) {
  const id = interceptors.response.length;
  interceptors.response.push({ onFulfilled, onRejected });
  return id;
}

/**
 * 移除拦截器
 * @param {string} type 类型 ('request' | 'response')
 * @param {number} id 拦截器ID
 */
export function removeInterceptor(type, id) {
  if (interceptors[type] && interceptors[type][id]) {
    interceptors[type][id] = null;
  }
}

/**
 * 上传文件
 * @param {string} url 上传URL
 * @param {File|FormData} file 文件或表单数据
 * @param {Object} options 选项
 * @returns {Promise} 上传结果
 */
export function upload(url, file, options = {}) {
  let formData;

  if (file instanceof FormData) {
    formData = file;
  } else {
    formData = new FormData();
    formData.append('file', file);
  }

  // 移除Content-Type，让浏览器自动设置
  const headers = { ...options.headers };
  delete headers['Content-Type'];

  return post(url, formData, {
    ...options,
    headers
  });
}

/**
 * 下载文件
 * @param {string} url 下载URL
 * @param {string} filename 文件名
 * @param {Object} options 选项
 * @returns {Promise} 下载结果
 */
export async function download(url, filename, options = {}) {
  try {
    const response = await fetch(url, options);

    if (!response.ok) {
      throw new RequestError(`Download failed: ${response.statusText}`, response.status);
    }

    const blob = await response.blob();

    // 创建下载链接
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = filename || 'download';

    // 触发下载
    document.body.appendChild(link);
    link.click();

    // 清理
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrl);

    return blob;
  } catch (error) {
    throw new RequestError(`Download failed: ${error.message}`, 'DOWNLOAD_ERROR');
  }
}

/**
 * 创建请求实例
 * @param {Object} config 配置对象
 * @returns {Object} 请求实例
 */
export function create(config = {}) {
  const instanceConfig = {
    ...DEFAULT_CONFIG,
    ...config
  };

  const instance = {
    config: instanceConfig,

    request(url, options = {}) {
      return request(url, { ...instanceConfig, ...options });
    },

    get(url, options = {}) {
      return this.request(url, { ...options, method: 'GET' });
    },

    post(url, data, options = {}) {
      return this.request(url, { ...options, method: 'POST', data });
    },

    put(url, data, options = {}) {
      return this.request(url, { ...options, method: 'PUT', data });
    },

    delete(url, options = {}) {
      return this.request(url, { ...options, method: 'DELETE' });
    },

    patch(url, data, options = {}) {
      return this.request(url, { ...options, method: 'PATCH', data });
    }
  };

  return instance;
}

// 导出默认实例
export default {
  request,
  get,
  post,
  put,
  delete: del,
  patch,
  head,
  all,
  race,
  upload,
  download,
  create,
  addRequestInterceptor,
  addResponseInterceptor,
  removeInterceptor
};
